/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**	* Redistributions of source code must retain the above copyright
**		notice, this list of conditions and the following disclaimer.
**	* Redistributions in binary form must reproduce the above copyright
**		notice, this list of conditions and the following disclaimer in
**		the documentation and/or other materials provided with the
**		distribution.
**	* Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
**		of its contributors may be used to endorse or promote products derived
**		from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/


#include "qtsingleapplication.h"
#include "qtlocalpeer.h"
#include <QWidget>


/*!
	\class QtSingleApplication qtsingleapplication.h
	\brief The QtSingleApplication class provides an API to detect and
	communicate with running instances of an application.

	This class allows you to create applications where only one
	instance should be running at a time. I.e., if the user tries to
	launch another instance, the already running instance will be
	activated instead. Another usecase is a client-server system,
	where the first started instance will assume the role of server,
	and the later instances will act as clients of that server.

	By default, the full path of the executable file is used to
	determine whether two processes are instances of the same
	application. You can also provide an explicit identifier string
	that will be compared instead.

	The application should create the QtSingleApplication object early
	in the startup phase, and call isRunning() to find out if another
	instance of this application is already running. If isRunning()
	returns false, it means that no other instance is running, and
	this instance has assumed the role as the running instance. In
	this case, the application should continue with the initialization
	of the application user interface before entering the event loop
	with exec(), as normal.

	The messageReceived() signal will be emitted when the running
	application receives messages from another instance of the same
	application. When a message is received it might be helpful to the
	user to raise the application so that it becomes visible. To
	facilitate this, QtSingleApplication provides the
	setActivationWindow() function and the activateWindow() slot.

	If isRunning() returns true, another instance is already
	running. It may be alerted to the fact that another instance has
	started by using the sendMessage() function. Also data such as
	startup parameters (e.g. the name of the file the user wanted this
	new instance to open) can be passed to the running instance with
	this function. Then, the application should terminate (or enter
	client mode).

	If isRunning() returns true, but sendMessage() fails, that is an
	indication that the running instance is frozen.

	Here's an example that shows how to convert an existing
	application to use QtSingleApplication. It is very simple and does
	not make use of all QtSingleApplication's functionality (see the
	examples for that).

	\code
	// Original
	int main(int argc, char **argv)
	{
		QApplication app(argc, argv);

		MyMainWidget mmw;
		mmw.show();
		return app.exec();
	}

	// Single instance
	int main(int argc, char **argv)
	{
		QtSingleApplication app(argc, argv);

		if (app.isRunning())
			return !app.sendMessage(someDataString);

		MyMainWidget mmw;
		app.setActivationWindow(&mmw);
		mmw.show();
		return app.exec();
	}
	\endcode

	Once this QtSingleApplication instance is destroyed (normally when
	the process exits or crashes), when the user next attempts to run the
	application this instance will not, of course, be encountered. The
	next instance to call isRunning() or sendMessage() will assume the
	role as the new running instance.

	For console (non-GUI) applications, QtSingleCoreApplication may be
	used instead of this class, to avoid the dependency on the QtGui
	library.

	\sa QtSingleCoreApplication
*/


void QtSingleApplication::sysInit(const QString &appId)
{
	actWin = 0;
	peer = new QtLocalPeer(this, appId);
	connect(peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived);
}


/*!
	Creates a QtSingleApplication object. The application identifier
	will be QCoreApplication::applicationFilePath(). \a argc, \a
	argv, and \a GUIenabled are passed on to the QAppliation constructor.

	If you are creating a console application (i.e. setting \a
	GUIenabled to false), you may consider using
	QtSingleCoreApplication instead.
*/

QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
	: QApplication(argc, argv, GUIenabled)
{
	sysInit();
}


/*!
	Creates a QtSingleApplication object with the application
	identifier \a appId. \a argc and \a argv are passed on to the
	QAppliation constructor.
*/

QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
	: QApplication(argc, argv)
{
	sysInit(appId);
}

#if QT_VERSION < 0x050000

/*!
	Creates a QtSingleApplication object. The application identifier
	will be QCoreApplication::applicationFilePath(). \a argc, \a
	argv, and \a type are passed on to the QAppliation constructor.
*/
QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
	: QApplication(argc, argv, type)
{
	sysInit();
}


#	if defined(Q_OS_LINUX)
/*!
	Special constructor for X11, ref. the documentation of
	QApplication's corresponding constructor. The application identifier
	will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
	and \a cmap are passed on to the QApplication constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
	: QApplication(dpy, visual, cmap)
{
	sysInit();
}

/*!
	Special constructor for X11, ref. the documentation of
	QApplication's corresponding constructor. The application identifier
	will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
	argv, \a visual, and \a cmap are passed on to the QApplication
	constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
	: QApplication(dpy, argc, argv, visual, cmap)
{
	sysInit();
}

/*!
	Special constructor for X11, ref. the documentation of
	QApplication's corresponding constructor. The application identifier
	will be \a appId. \a dpy, \a argc, \a
	argv, \a visual, and \a cmap are passed on to the QApplication
	constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
	: QApplication(dpy, argc, argv, visual, cmap)
{
	sysInit(appId);
}
#	endif // Q_OS_LINUX
#endif // QT_VERSION < 0x050000


/*!
	Returns true if another instance of this application is running;
	otherwise false.

	This function does not find instances of this application that are
	being run by a different user (on Windows: that are running in
	another session).

	\sa sendMessage()
*/

bool QtSingleApplication::isRunning()
{
	return peer->isClient();
}


/*!
	Tries to send the text \a message to the currently running
	instance. The QtSingleApplication object in the running instance
	will emit the messageReceived() signal when it receives the
	message.

	This function returns true if the message has been sent to, and
	processed by, the current instance. If there is no instance
	currently running, or if the running instance fails to process the
	message within \a timeout milliseconds, this function return false.

	\sa isRunning(), messageReceived()
*/
bool QtSingleApplication::sendMessage(const QString &message, int timeout)
{
	return peer->sendMessage(message, timeout);
}


/*!
	Returns the application identifier. Two processes with the same
	identifier will be regarded as instances of the same application.
*/
QString QtSingleApplication::id() const
{
	return peer->applicationId();
}


/*!
	Sets the activation window of this application to \a aw. The
	activation window is the widget that will be activated by
	activateWindow(). This is typically the application's main window.

	If \a activateOnMessage is true (the default), the window will be
	activated automatically every time a message is received, just prior
	to the messageReceived() signal being emitted.

	\sa activateWindow(), messageReceived()
*/

void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
{
	actWin = aw;
	if (activateOnMessage)
		connect(peer, &QtLocalPeer::messageReceived, this, qOverload<>(&QtSingleApplication::activateWindow));
	else
		disconnect(peer, &QtLocalPeer::messageReceived, this, qOverload<>(&QtSingleApplication::activateWindow));
}


/*!
	Returns the applications activation window if one has been set by
	calling setActivationWindow(), otherwise returns 0.

	\sa setActivationWindow()
*/
QWidget* QtSingleApplication::activationWindow() const
{
	return actWin;
}


/*!
	De-minimizes, raises, and activates this application's activation window.
	This function does nothing if no activation window has been set.

	This is a convenience function to show the user that this
	application instance has been activated when he has tried to start
	another instance.

	This function should typically be called in response to the
	messageReceived() signal. By default, that will happen
	automatically, if an activation window has been set.

	\sa setActivationWindow(), messageReceived(), initialize()
*/
void QtSingleApplication::activateWindow()
{
	if (actWin) {
		actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
		actWin->raise();
		actWin->activateWindow();
	}
}


/*!
	\fn void QtSingleApplication::messageReceived(const QString& message)

	This signal is emitted when the current instance receives a \a
	message from another instance of this application.

	\sa sendMessage(), setActivationWindow(), activateWindow()
*/


/*!
	\fn void QtSingleApplication::initialize(bool dummy = true)

	\obsolete
*/
